#pragma once

namespace bs
{
	class IMoveable
	{
	public:
		IMoveable();
		virtual ~IMoveable();

		virtual void DoMove(float speedFactor);
		virtual void OnReachEdge() {}
		virtual bool CollisionWith(IMoveable* other);

		void EnableMove(bool enable) { this->canMove = enable; }
		void EnabelMaxVel(bool enable) { this->enableMaxVel = enable; }
		void EnableBounds(bool enable) { this->enableBounds = enable; }
		void EnableMoveOut(bool enable) { this->canMoveOut = enable; }  // if true, it can move out the bounds and call OnReachEdge, else stops on the bounds

 		void SetPos(float _x, float _y) { this->x = _x; this->y = _y; }
 		void SetVel(float _vx, float _vy) { this->vx = _vx; this->vy = _vy; }
 		void SetAccel(float _ax, float _ay) { this->ax = _ax; this->ay = _ay; }
		void SetFriction(float _friX, float _friY) { this->friX = _friX; this->friY = _friY; } // just available when accel is zero
		void SetMaxVel(float _maxVx, float _maxVy) { this->maxVx = _maxVx; this->maxVy = _maxVy; }
		void SetBounds(float _minX, float _minY, float _maxX, float _maxY) { this->minX = _minX; this->minY = _minY; this->maxX = _maxX; this->maxY = _maxY; }
		void SetCollisionOffset(int left, int top, int right, int bottom) 
		{ this->collisionLeftOff = left; this->collisionTopOff = top; this->collisionRightOff = right; this->collistionBottomOff = bottom; }

		int GetWidth() const { return this->w; }
		int GetHeight() const { return this->h; }
		void GetPos(float& _x, float& _y) const { _x = this->x; _y = this->y; }
		void GetVel(float& _vx, float& _vy) const { _vx = this->vx; _vy = this->vy; }

	protected:
		void CheckPos();
		void AdjustVelWithFricrion(float speedFactor);
		void AdjustMaxVel();

	protected:
		int   w, h;
		float x, y;
		float vx, vy;
		float ax, ay;
		float friX, friY;
		float maxVx, maxVy;
		float minX, minY, maxX, maxY;

		int collisionLeftOff,
			collisionTopOff,
			collisionRightOff,
			collistionBottomOff;

		bool outOfBounds;

		bool canMove;
		bool enableMaxVel;
		bool enableBounds;
		bool canMoveOut;
	};

}
